#include"MMySql.h"
#include<iostream>
#include"error.h"
#include <chrono>
#include <ctime>
#include <iomanip>
#include<iostream>

//创建文件夹头文件
#include<sys/stat.h>
#include<sys/types.h>
#include<locale.h>
#include<cstdlib>
#include"sever.h"

#include"agreement.h"

MMySql::MMySql(const std::string host,const std::string username,
        const std::string userpassword,const std::string dateName, const unsigned int port):con(nullptr)
{
      try {
        // 获取MySQL驱动实例
        driver = sql::mysql::get_mysql_driver_instance();
        
        // 建立数据库连接
        con = driver->connect(
            "tcp://" + host + ":" + std::to_string(port),
            username,
            userpassword
        );
        
        // 选择数据库
        con->setSchema(dateName);
        
        // 设置字符集
        con->setClientOption("characterEncoding", "utf8");
        
        successConnection = true;
    } catch (sql::SQLException& e) {
        std::cerr << "数据库连接错误: " << e.what() 
                  << " (SQLState: " << e.getSQLState() << ")" << std::endl;
        successConnection = false;
    }
}

MMySql::~MMySql()
{
    if(con){
        delete con;
    }
}

void MMySql::setOnline(int phone,bool flag)
{
    if (!con || !successConnection) {
        std::cerr << "数据库连接失败，无法设置在线状态" << std::endl;
        return;
    }
    
    try {
        con->setAutoCommit(false);
        std::unique_ptr<sql::PreparedStatement> pstmt(
            con->prepareStatement("UPDATE userInfo SET online = ? WHERE phone = ?")
        );
        pstmt->setBoolean(1, flag);
        pstmt->setInt(2, phone);
        pstmt->executeUpdate();
        
        std::cout << "设置用户 " << phone << " 在线状态为: " << (flag ? "在线" : "离线") << std::endl;
        con->commit();
        con->setAutoCommit(true);
    } catch (const sql::SQLException& e) {
        con->rollback();
        con->setAutoCommit(true);
        std::cerr << "SQL错误: " << e.what() << std::endl;
        std::cerr << "错误代码: " << e.getErrorCode() << std::endl;
        successConnection = false; // 标记连接需要重新建立
    }

}

CloudDrive::MessageReturn MMySql::enroll(int phone, std::string username, std::string userpass, std::string email)
{
    std::string strpath = "./data/" + std::to_string(phone);
    if(!con || !successConnection) return CloudDrive::MessageReturn::REGISTER_NO;
    try{
        con->setAutoCommit(false);
        // 创建预处理语句
        std::unique_ptr<sql::PreparedStatement> pstmt1(
            con->prepareStatement("SELECT phone FROM userInfo WHERE phone = ?")
        );
        pstmt1->setInt(1,phone);
        // 执行查询并获取结果集
        std::unique_ptr<sql::ResultSet> res(pstmt1->executeQuery());
        if(res->next()) return CloudDrive::MessageReturn::REGISTER_EXIST;

        // 创建预处理语句
        std::unique_ptr<sql::PreparedStatement> pstmt(
            con->prepareStatement("INSERT INTO userInfo(phone, userName, userpass, email, regdate) VALUES(?, ?, ?, ?, NOW())")
        );

        // 设置参数
        pstmt->setInt(1, phone);
        pstmt->setString(2, username);
        pstmt->setString(3, userpass);
        pstmt->setString(4, email);
        
        // 执行语句
        pstmt->execute();

        // // 创建文件夹
        mode_t mode = 0777;
        if(mkdir(strpath.c_str(),mode)!=0) return CloudDrive::MessageReturn::REGISTER_NO;
        con->commit();
        con->setAutoCommit(true);
        return CloudDrive::MessageReturn::REGISTER_OK;
    }
    catch(sql::SQLException &e){
        std::cerr << "插入失败 " << e.what() 
                  << " (SQLState: " << e.getSQLState() << ")" << std::endl;
        con->rollback();
        con->setAutoCommit(true);
        rmdir(strpath.c_str());
        // }
        return CloudDrive::MessageReturn::REGISTER_NO;
    }
}


CloudDrive::MessageReturn MMySql::Login(int phone, std::string userpass)
{        
    if(!con || !successConnection) return CloudDrive::MessageReturn::LOGIN_NO;
    try
    {
        con->setAutoCommit(false);
        // 创建预处理语句
        std::unique_ptr<sql::PreparedStatement> pstmt1(
            con->prepareStatement("SELECT * FROM userInfo WHERE phone = ? and userpass = ? and online = 0")
        );
        pstmt1->setInt(1,phone);
        pstmt1->setString(2,userpass);
        // 执行查询并获取结果集
        std::unique_ptr<sql::ResultSet> res(pstmt1->executeQuery());

        if(res->next()) {
            setOnline(phone,true);
            con->commit();
            con->setAutoCommit(true);
            return CloudDrive::MessageReturn::LOGIN_OK;
        }
        con->commit();
        con->setAutoCommit(true);
        return CloudDrive::MessageReturn::LOGIN_NOTEXIST;
    }
    catch(const std::exception& e)
    {
        con->rollback();
        con->setAutoCommit(true);
        return CloudDrive::MessageReturn::LOGIN_NO;
    }
}

CloudDrive::MesBack MMySql::Refresh(int phone)
{
    CloudDrive::MesBack msg;
    msg.firendCount = 0;

    if(!con || !successConnection) msg.type = CloudDrive::MessageReturn::REFRESH_NO;
    else{
        try
        {          
            con->setAutoCommit(false);
            std::unique_ptr<sql::PreparedStatement> pstmt1(
            con->prepareStatement("SELECT user2Phone FROM FriendList WHERE user1Phone = ? union SELECT user1Phone FROM FriendList WHERE user2Phone = ?")
            );
            pstmt1->setInt(1,phone);
            pstmt1->setInt(2,phone);
            std::unique_ptr<sql::ResultSet> res(pstmt1->executeQuery());

            while(res->next()){
                int phone1 = res->getInt(1);
                std::unique_ptr<sql::PreparedStatement> pstmt2(
                    con->prepareStatement("SELECT userName FROM userInfo WHERE phone = ?")
                );
                pstmt2->setInt(1,phone1);
                std::unique_ptr<sql::ResultSet> resn(pstmt2->executeQuery());
                std::string name;
                while (resn->next())
                {
                    name = resn->getString(1);
                }
                msg.friends[msg.firendCount].id = phone1;
                std::memcpy(msg.friends[msg.firendCount].name,name.c_str(),sizeof(name));
                msg.firendCount++;
            }
            con->commit();
            con->setAutoCommit(true);
        }
         catch (const sql::SQLException& e) {
        // 发生异常时回滚事务
            try {
                if (con) con->rollback();
            } catch (const sql::SQLException&) {
                // 处理回滚失败的情况
            }
            msg.type = CloudDrive::MessageReturn::REFRESH_NO;
            con->setAutoCommit(true);
        }
    }
    return msg;
}

void MMySql::addFriend(int user1, int user2)
{
    if(!con || !successConnection) return;
    try
    {
        con->setAutoCommit(false);
        
        // 检查好友关系是否已存在（包含两种可能的顺序）
        std::unique_ptr<sql::PreparedStatement> pstmt(
            con->prepareStatement("SELECT * FROM FriendList WHERE (user1Phone = ? AND user2Phone = ?) "
                                  "UNION "
                                  "SELECT * FROM FriendList WHERE (user1Phone = ? AND user2Phone = ?)")
        );
        pstmt->setInt(1, user1);
        pstmt->setInt(2, user2);
        pstmt->setInt(3, user2);
        pstmt->setInt(4, user1);
        
        std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
        if(res->next()) {
            con->rollback();
            con->setAutoCommit(true);
            return;
        }
        
        // 插入新的好友关系
        std::unique_ptr<sql::PreparedStatement> pstmt1(
            con->prepareStatement("INSERT INTO FriendList(user1Phone, user2Phone) VALUES(?, ?)")
        );
        pstmt1->setInt(1, user1);
        pstmt1->setInt(2, user2);
        pstmt1->executeUpdate();
        
        // 提交事务
        con->commit();
        con->setAutoCommit(true);
    }
    catch(const std::exception& e)
    {
        con->rollback();
        con->setAutoCommit(true);
    }
    
 
}

CloudDrive::MessageReturn MMySql::deletFriend(int user1, int user2)
{
    if(!con || !successConnection) return CloudDrive::MessageReturn::DELETE_FRIEND_NO;
    try{
        con->setAutoCommit(false);
                // 检查好友关系是否已存在（包含两种可能的顺序）
        std::unique_ptr<sql::PreparedStatement> pstmt(
        con->prepareStatement("DELETE FROM FriendList WHERE ((user1Phone = ? AND user2Phone = ?)"
                            " OR (user1Phone = ? AND user2Phone = ?))")
        );
        pstmt->setInt(1, user1);
        pstmt->setInt(2, user2);
        pstmt->setInt(3, user2);
        pstmt->setInt(4, user1);
        pstmt->executeUpdate();

        con->commit(); 
        con->setAutoCommit(true);
        return CloudDrive::MessageReturn::DELETE_FRIEND_OK;
    }
    catch(const std::exception& e){
        con->rollback();
        con->setAutoCommit(true);
        return CloudDrive::MessageReturn::DELETE_FRIEND_NO;
    }
}
